﻿/*****************************************************************//**
 * @file    PickedDataProvider.h
 * @brief   拾取数据管理类。（并未三维可视化对象管理）
 *
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-10-31
 *********************************************************************/

#ifndef __PICKEDDATAPROVIDER_H__
#define __PICKEDDATAPROVIDER_H__

#include <QObject>

#include "PickDataProviderAPI.h"

#include <QHash>

 // 前置声明
class vtkActor;
class vtkActor2D;
class vtkImageActor;
class vtkPlanes;

namespace AppFrame
{
    class FITKKeyMouseStates;
}

namespace GraphData
{
    class PickedData;
}

namespace GraphData
{
    /**
     * @brief   拾取数据管理类。（并未三维可视化对象管理）
     * @author  ChengHaotian (yeguangbaozi@foxmail.com)
     * @date    2024-10-31
     */
    class PICKDATAPROVIDERAPI PickedDataProvider : public QObject
    {
        Q_OBJECT
    public:
        /**
         * @brief   获取单例。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        static PickedDataProvider* getInstance();

        /**
         * @brief   手动销毁。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        static void Delete();

        /**
         * @brief   清空拾取数据。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        void clearPickedData();

        /**
         * @brief   生成拾取数据。
         * @param   actor：拾取演员
         * @param   index：拾取索引
         * @param   pickedWorldPos：拾取的世界坐标
         * @return  预选或拾取数据。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        PickedData* getPickedData(vtkActor* actor, int index, double* pickedWorldPos);

        /**
         * @brief   生成拾取数据。
         * @param   actor：拾取演员
         * @return  预选或拾取数据。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        PickedData* getPickedData(vtkActor2D* actor);

        /**
         * @brief   生成拾取数据。
         * @param   actor：拾取演员
         * @return  预选或拾取数据。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-11-07
         */
        PickedData* getPickedData(vtkImageActor* actor);

        /**
         * @brief   添加单次点击拾取三维对象数据。
         * @param   actor：拾取演员
         * @param   index：拾取索引
         * @param   pickedWorldPos：拾取的世界坐标
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        void addPicked(vtkActor* actor, int index, double* pickedWorldPos);

        /**
         * @brief   添加单次点击拾取二维对象数据。
         * @param   actor：拾取演员
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        void addPicked(vtkActor2D* actor);

        /**
         * @brief   添加单次点击拾取图片对象数据。
         * @param   actor：拾取演员
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-11-07
         */
        void addPicked(vtkImageActor* actor);

        /**
         * @brief   添加单词框选拾取多个演员信息。
         * @param   actors：拾取演员列表
         * @param   pickPlanes：拾取器裁切面
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-11-02
         */
        void addPicked(QList<vtkActor*> actors, vtkPlanes* pickPlanes);

        /**
         * @brief   获取拾取数据列表。
         * @return  拾取信息
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        QList<PickedData*> getPickedList();

    signals:
        ;
        /**
         * @brief    拾取结束信号
         * @author   BaGuijun (baguijun@163.com)
         * @date     2025-02-18
         */
        void sig_pickedOver();
        /**
         * @brief    拾取到对象信号
         * @author   BaGuijun (baguijun@163.com)
         * @date     2025-02-18
         */
        void sig_pickedData();
    protected:
        /**
         * @brief   构造函数。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        PickedDataProvider();

        /**
         * @brief   析构函数。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        ~PickedDataProvider();

        /**
         * @brief   根据键盘事件处理拾取数据。
         * @param   data：拾取数据
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        void dealPickedData(PickedData* data);

    private:
        /**
         * @brief   找到相同模型点拾取数据，不存在则返回空。
         * @param   data：查找数据的依据
         * @return  找到的数据
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        PickedData* getSameModelPickData(PickedData* data);

        /**
         * @brief   检查拾取数据，高亮数据并发送数据拾取信号。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-11-02
         */
        void checkPickData();

        /**
         * @brief   根据拾取模式与键盘按下情况判断是否需要清空拾取数据。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-11-04
         */
        void clearDataIfNeccessary();

    private:
        /**
         * @brief   实例。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        static PickedDataProvider* s_instance;

        /**
         * @brief   系统键盘监视器。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        AppFrame::FITKKeyMouseStates* m_keyStates{ nullptr };

        /**
         * @brief   所有拾取信息。
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-10-31
         */
        QList<PickedData*> m_pickedDataList;

    };
}

#endif // __PICKEDDATAPROVIDER_H__
